import useTokenStore from "@/stores/token";
import { CODE } from "./constants";
import { catch_error_resp } from "./request";

export default class ChatStream {
    #url;
    #controller;
    constructor(url) {
        this.#url = url;
        this.#controller = null;
        this.onMessage = () => {};
        this.onFinish = () => {};
        this.onError = () => {};
    }

    async send({
        chatMsg,
        chatDialog,
        isNew,
    }) {
        this.#controller = new AbortController();
        let reader;
        
        try {
            const response = await fetch(this.#url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Accept': 'text/event-stream',
                    'Authorization': useTokenStore().getAuthHeader().Authorization
                },
                body: JSON.stringify({
                    chatMsg,
                    chatDialog,
                    isNew, 
                }),
                signal: this.#controller.signal
            });


            reader = response.body.getReader();
            const decoder = new TextDecoder();
            
            while(true) {
                const { done, value } = await reader.read();
                if(done) {
                    break;
                }

                const chunk = decoder.decode(value);
                chunk.split('\n\n').forEach(event => {
                    if(event.startsWith('data:')) {
                        const data = event.replace('data:','').trim();
                        const jsonObj = JSON.parse(data);
                        const dataObj = {
                            code: jsonObj.code,
                            msg: jsonObj.msg,
                            data: jsonObj.data ? jsonObj.data : null
                        }
                        this.onMessage(dataObj);
                    }
                });
            }
        } catch(err) {
            if(err.name === 'AbortError') {
                return
            }
            let error_resp = undefined
            if (err instanceof SyntaxError) {
                console.error("ChatStream send: 解析失败:", err)
                error_resp = { code: CODE.SERVER_COMMON_ERROR, msg: `解析后端返回数据格式失败` }
            } else {
                error_resp = catch_error_resp(err)
            }
            this.onError(error_resp);
        } finally {
            reader?.releaseLock();
            this.onFinish();
            this.#controller = null;
        }
    }

    isChating() {
        return this.#controller !== null
    }

    abort() {
        if(this.isChating()) {
            this.#controller.abort();
        }
    }
}